package com.tuo51.evaluate.service.impl;

import com.tuo51.evaluate.domain.evaluatingV2.EvaluateV2MonthConclusion;
import com.tuo51.evaluate.domain.evaluatingV2.EvaluateV2Record;
import com.tuo51.evaluate.domain.evaluatingV2.EvaluateV2RecordDimensionScore;
import com.tuo51.evaluate.repositories.AnswerNativeRepository;
import com.tuo51.evaluate.repositories.evaluatev2.EvaluateV2MonthConclusionRepository;
import com.tuo51.evaluate.service.EvaluateV2ConclusionService;
import com.tuo51.evaluate.vo.evaluate.EvaluateV2AnswerVO;
import com.tuo51.foudation.exception.BusinessException;
import com.tuo51.foudation.model.ErrorCode;
import com.tuo51.foudation.utils.DateUtil;
import com.tuo51.foudation.utils.EvaluationReportUtils;
import com.tuo51.foudation.utils.export.HealthReportUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.stereotype.Service;

import java.util.*;

import static com.tuo51.evaluate.service.EvaluateV2ConclusionService.ReportRatings.*;
import static com.tuo51.evaluate.service.EvaluateV2Service.WARNING_DIMENSION_ID;

@Service
@Slf4j
@CacheConfig(cacheNames = "EvaluateV2ConclusionServiceImpl")
public class EvaluateV2ConclusionServiceImpl implements EvaluateV2ConclusionService {

    @Autowired
    private AnswerNativeRepository answerRepository;

    @Autowired
    private EvaluateV2MonthConclusionRepository monthConclusionRepository;

    @Override
    public String getWarningConclusion(EvaluateV2Record record) {
        int warningValue = 0;
        for (int i = 0; i < record.getDimensionScores().size(); i++) {
            EvaluateV2RecordDimensionScore c = record.getDimensionScores().get(i);
            if (c.getDimensionId().equals(WARNING_DIMENSION_ID)) {
                warningValue = c.getScore() / 10;
                break;
            }
        }

        //评分低于7分视为正常，7-11分随访，12-30分存在交流互动障碍危险，大于30分高度疑似ASD
        // 交流互动警示行为这个项目，
        // 7-11分测评描述：由于电子产品的不断更新，人机对话的时间增加，忽视人与人交往在儿童发育中的重要作用，亲子关系疏离可能影响婴幼儿的社会交往能力。
        // 12-30分测评描述：社会性和交流能力方面有明显得缺陷，建议带宝宝去心理专科咨询诊断。
        // 30分以上：高度怀疑ASD，建议带宝宝去心理专科咨询诊断。

        String warnStr = "";
        if (warningValue > 7 && warningValue <= 12) {
            warnStr = "由于电子产品的不断更新，人机对话的时间增加，忽视人与人交往在儿童发育中的重要作用，亲子关系疏离可能影响婴幼儿的社会交往能力。";
        } else if (warningValue > 12 && warningValue <= 30) {
            warnStr = "社会性和交流能力方面有明显的缺陷，建议带宝宝去心理专科咨询诊断。";
        } else if (warningValue > 30) {
            warnStr = "高度怀疑ASD，建议带宝宝去心理专科咨询诊断。";
        }

        return warnStr;
    }

    @Override
    public String getNormalConclusion(EvaluateV2Record record) {

        List<EvaluateV2RecordDimensionScore> A = new ArrayList<>();
        List<EvaluateV2RecordDimensionScore> Ap = new ArrayList<>();
        List<EvaluateV2RecordDimensionScore> Am = new ArrayList<>();

        for(int i = 0 ; i < record.getDimensionScores().size(); i++){
            EvaluateV2RecordDimensionScore c = record.getDimensionScores().get(i);
            if(WARNING_DIMENSION_ID.equals(c.getDimensionId())){
                continue;
            }
            String rating = dqRating(c.getDq()/10);
            ReportRatings r = ReportRatings.forRating(rating);

            if (r == REPORT_RATING_A){
                //正常项目
                A.add(c);
            }else if(r.getValue() < REPORT_RATING_A.getValue()){
                //优势项目
                Ap.add(c);
            }else if(r.getValue() > REPORT_RATING_A.getValue()){
                //劣势项目
                Am.add(c);
            }
        }

        final String apStr = "非常好，较同龄宝宝而言处于优势水平，请继续保持或可探索宝宝的特长培养；";
        final String aStr = "处于正常水平，请保持关注；";
        final String amStr = "相对较弱，需进一步加强，家长应适当干预，并咨询老师或专家获取相关提升方案；";

        StringBuilder tipStr = new StringBuilder();
        tipStr.append("从测评结果来看，"+record.getChildrenName() + "宝宝");

        generateConclusionPart(tipStr, Ap, apStr);
        generateConclusionPart(tipStr, A, aStr);
        generateConclusionPart(tipStr, Am, amStr);

        if(tipStr.substring(tipStr.length() - 1).equals("；")){
            tipStr.replace(tipStr.length() - 1 , tipStr.length(), "。");
        }

        return tipStr.toString();
    }

    @Override
    public String getDQComparingConclusion(EvaluateV2Record record, EvaluateV2Record comparingRecord){
//        1.  从不合格（或合格）到提升后优秀
//        2.  从不合格提升到正常
//        3.  从不合格提升到不合格---有了进步但是还需要家长和老师干预
//        4.  从优秀下降到达标（比较报告不出现）
//        5.  从优秀下降到不达标
//        6.  平稳发展（比较报告不出现）
        if(!record.getChildrenId().equals(comparingRecord.getChildrenId())){
            throw new BusinessException(ErrorCode.EVALUATE_NO_MATCH, "宝宝不一致");
        }
        if(record.getDimensionScores().size() != comparingRecord.getDimensionScores().size()){
            throw new BusinessException(ErrorCode.EVALUATE_NO_MATCH, "测评报告计分数量不一致");
        }

        List<EvaluateV2RecordDimensionScore[]> up = new ArrayList<>();
        List<EvaluateV2RecordDimensionScore[]> upFast = new ArrayList<>();
        List<EvaluateV2RecordDimensionScore[]> down = new ArrayList<>();
        List<EvaluateV2RecordDimensionScore[]> downFast = new ArrayList<>();
        List<EvaluateV2RecordDimensionScore[]> stable = new ArrayList<>();
        List<EvaluateV2RecordDimensionScore[]> upstableLow = new ArrayList<>();

        for(int i = 0 ; i < record.getDimensionScores().size(); i++){
            EvaluateV2RecordDimensionScore r = record.getDimensionScores().get(i);
            EvaluateV2RecordDimensionScore c = comparingRecord.getDimensionScores().get(i);
            if(!r.getDimensionId().equals(c.getDimensionId())){
                throw new BusinessException(ErrorCode.EVALUATE_NO_MATCH, "测评报告能区顺序不一致");
            }
            if(WARNING_DIMENSION_ID.equals(c.getDimensionId())){
                continue;
            }

            ReportRatings rr = ReportRatings.forRating(dqRating(r.getDq()/10));
            ReportRatings cr = ReportRatings.forRating(dqRating(c.getDq()/10));

            if(cr == rr){
                stable.add(new EvaluateV2RecordDimensionScore[]{r, c});

                if(rr.getValue() - REPORT_RATING_A.getValue() > 0){  //不达标
                    upstableLow.add(new EvaluateV2RecordDimensionScore[]{r, c});
                }
            }else if(rr.getValue() > cr.getValue()){  //降低

                down.add(new EvaluateV2RecordDimensionScore[]{r, c});

                if(rr.getValue() - REPORT_RATING_A.getValue() > 1){  //降得快
                    downFast.add(new EvaluateV2RecordDimensionScore[]{r, c});
                }
            }else{  //提高
                up.add(new EvaluateV2RecordDimensionScore[]{r, c});
                if(REPORT_RATING_A.getValue() - rr.getValue() > 1){  //提得快
                    upFast.add(new EvaluateV2RecordDimensionScore[]{r, c});
                }
                if(rr.getValue() - REPORT_RATING_A.getValue() > 0){  //不达标
                    upstableLow.add(new EvaluateV2RecordDimensionScore[]{r, c});
                }
            }
        }

        StringBuilder comparingConclusion = new StringBuilder();
        comparingConclusion.append("对比宝宝");
        comparingConclusion.append(DateUtil.parseToDateDay(comparingRecord.getEvaluatingDate()));
        comparingConclusion.append("的测评报告，");

        final String downTips = "请老师或者家长观察是否由于宝宝情绪低落、睡眠不足、饮食不规律或者生病等因素造成。";
        final String finalTips = "另外，家长可参照测评报告对应能区的“指导方案”及“能力拓展”章节对宝宝进行提升训练。";

        if(up.size() > 0){
            comparingConclusion.append(concatDimensionComparingScores(up));
            if (up.size() > 1){
                comparingConclusion.append(int2Chinese(up.size()));
            }

            if(upFast.size() != up.size()) {
                comparingConclusion.append("能区的发育商有了进步");

                if(upFast.size() > 0  ){
                    comparingConclusion.append("，其中");
                    comparingConclusion.append(concatDimensionComparingNames(upFast));
                    if (upFast.size() > 1){
                        comparingConclusion.append(int2Chinese(upFast.size()));
                    }
                    comparingConclusion.append("能区的发育商有了显著的提高，");
                }else{
                    comparingConclusion.append("，");
                }
            }else{
                comparingConclusion.append("能区的发育商均有显著的提高，");
            }
            comparingConclusion.append("这说明宝宝这");
            comparingConclusion.append(int2Chinese(stable.size()));
            comparingConclusion.append("能区的能力在突飞猛进的发展，");
            comparingConclusion.append("请家长和老师继续保持，并关注宝宝的成长发育；");
        }

        boolean needFinalTips = false;
        if(stable.size() > 0){
            comparingConclusion.append(concatDimensionComparingScores(stable));
            if (stable.size() > 1){
                comparingConclusion.append(int2Chinese(stable.size()));
            }
            comparingConclusion.append("能区的发育商等级评价没有变化");

//            comparingConclusion.append("能区的发育商保持稳定，这说明宝宝这");
//            comparingConclusion.append(int2Chinese(stable.size()));
//            comparingConclusion.append("能区的能力在稳步发展");

            if(upstableLow.size() > 0){
                comparingConclusion.append("，但");
                if(upstableLow.size() == stable.size()){
                    comparingConclusion.append("这");
                    comparingConclusion.append(int2Chinese(stable.size()));
                }else {
                    comparingConclusion.append(concatDimensionComparingNames(upstableLow));
                    if (upstableLow.size() > 1) {
                        comparingConclusion.append(int2Chinese(stable.size()));
                    }
                }
                comparingConclusion.append("能区的发育水平仍然相对偏低，需进一步加强，家长应适当干预；");
                needFinalTips = true;
            }else{
                comparingConclusion.append("；");
            }
        }else if(upstableLow.size() > 0){
            comparingConclusion.append("不过，");
            comparingConclusion.append(concatDimensionComparingNames(upstableLow));
            if (upstableLow.size() > 1) {
                comparingConclusion.append(int2Chinese(stable.size()));
            }
            needFinalTips = true;
            comparingConclusion.append("能区的发育水平仍然相对偏低，需进一步加强，家长应适当干预；");
        }

        if(down.size() > 0){
            if(up.size() + stable.size() > 0){
                comparingConclusion.append("而");
            }
            comparingConclusion.append(concatDimensionComparingScores(down));
            if (down.size() > 1){
                comparingConclusion.append(int2Chinese(down.size()));
            }

            if( downFast.size() != down.size()) {
                comparingConclusion.append("能区的发育商有所下降");

                if(downFast.size() > 0){
                    comparingConclusion.append("，其中");
                    comparingConclusion.append(concatDimensionComparingNames(downFast));
                    if (downFast.size() > 1){
                        comparingConclusion.append(int2Chinese(downFast.size()));
                    }
                    comparingConclusion.append("能区的发育商下降尤为明显，");
                    comparingConclusion.append(downTips);
                }else{
                    comparingConclusion.append("。");
                }
            }else{
                comparingConclusion.append("能区的发育商均有明显下降，");
                comparingConclusion.append(downTips);
            }

            needFinalTips = true;
        }

        if(needFinalTips){
            comparingConclusion.append(finalTips);
        }

        return comparingConclusion.toString();
    }

    private static final String TIPSTR_dd = "能区发育";
    private static final String TIPSTR_all = "皆";

    private void generateConclusionPart(StringBuilder c, List<EvaluateV2RecordDimensionScore> ds, String tail){


        if(ds.size() >0){
            c.append(concatDimensionScores(ds));
            if (ds.size()>1){
                c.append(int2Chinese(ds.size()));
            }
            c.append(TIPSTR_dd);
            if(ds.size() == 5){
                c.append(TIPSTR_all);
            }
            c.append(tail);
        }
    }

    private String int2Chinese(int a){
        if(a < 0 || a > 5) a = 0;
        final String res[] = {"","一个","两个","三个","四个","五个"};
        return res[a];
    }
    private String concatDimensionComparingNames(List<EvaluateV2RecordDimensionScore[]>scores){
        String ret = "";

        for (EvaluateV2RecordDimensionScore score[] : scores){
            if(ret.length() > 0){
                ret += "、";
            }
            ret += score[0].getDimensionName() ;
        }

        return ret;
    }
    private String concatDimensionComparingScores(List<EvaluateV2RecordDimensionScore[]>scores){
        String ret = "";

        for (EvaluateV2RecordDimensionScore score[] : scores){
            if(ret.length() > 0){
                ret += "、";
            }
            int oldValue = (int)(score[1].getDq()/10.0 + 0.5);
            int newValue = (int)(score[0].getDq()/10.0 + 0.5);
            ret += String.format("%s（%d分 → %d分）", score[0].getDimensionName(), oldValue, newValue);
        }

        return ret;
    }

    private String concatDimensionScores(List<EvaluateV2RecordDimensionScore>scores){
        String ret = "";

        for (EvaluateV2RecordDimensionScore score : scores){
            if(ret.length() > 0){
                ret += "、";
            }
            int value = (int)(score.getDq()/10.0 + 0.5);
            ret += String.format("%s（%d分）", score.getDimensionName(), value);
        }

        return ret;
    }

    @Override
    public String getHeightComparingConclusion(EvaluateV2Record record, EvaluateV2Record comparingRecord){
        //宝宝本次实测身长75.00cm,按年龄测身长的百分位数为P80-P97。较上次实测宝宝增长5.00cm，宝宝按年龄测身长的百分位数略降到P80-P97阶段。较同龄宝宝而言还处于优秀水平，请继续保持。
        double height = 0;
        double pre_height = 0;

        if(StringUtils.isNotBlank(record.getHeight())) {
            height = Double.parseDouble(record.getHeight());
        }
        if(StringUtils.isNotBlank(comparingRecord.getHeight())){
            pre_height = Double.parseDouble(comparingRecord.getHeight());
        }

        String gender = record.getGender() == 0 ? "女" : "男";
        String heightPercent = HealthReportUtil.calcHeightPercent(record.getMonth(), gender, height );
        String preHeightPercent = HealthReportUtil.calcHeightPercent(record.getMonth(), gender, pre_height );

        int hi = HealthReportUtil.indexOfPercent(heightPercent) ;
        int phi = HealthReportUtil.indexOfPercent(preHeightPercent);

        StringBuilder conclusion = new StringBuilder();
        conclusion.append("如年龄身高曲线图所示，宝宝本次实测身高");
        conclusion.append(record.getHeight());
        conclusion.append("cm，");
        conclusion.append("较上次测评（");
        conclusion.append(DateUtil.parseToDateDay(comparingRecord.getEvaluatingDate()));

        if(height > pre_height) {
            conclusion.append("）长高了");
            conclusion.append(String.format("%.2fcm,",  height - pre_height));
        }else if(height < pre_height){
            conclusion.append("）变矮了");
            conclusion.append(String.format("%.2fcm,",  pre_height - height));
        }else{
            conclusion.append(") 没有变化。");
        }

        boolean needFinalTip = false;
        final String finalTip = "家长日常生活中应注意：\n" +
                "▪ 注意儿童在饭前约15分钟不要做剧烈运动，避免兴奋过度，影响正常食欲；\n" +
                "▪ 宝宝在睡觉期间是最容易长身体的，如果宝宝睡眠质量不佳或是睡眠不足，都会影响到身高发育。";

        conclusion.append("按年龄测身高的百分数");
        if(heightPercent.equals(preHeightPercent)){
            conclusion.append("保持在");
            conclusion.append(heightPercent);
            conclusion.append("水平稳步发展。");
            if(hi < 3   /*readablePercent  中*/){
                needFinalTip = true;
            }
        }else {
            if(hi < 3   /*readablePercent  中*/){
                needFinalTip = true;
            }
            conclusion.append("为");
            conclusion.append(heightPercent);
            conclusion.append("，较之前发育水平（");
            conclusion.append(preHeightPercent);
            if (hi > phi) {
                //增长了
                if(hi - phi < 2) {
                    conclusion.append("）有所提升。");
                }else{
                    conclusion.append("）显著提升。");
                }
            } else {
                //降低了
                if(phi - hi < 2) {
                    conclusion.append("）略有下降。");
                }else{
                    conclusion.append("）有所下降。");
                }
                needFinalTip = true;
            }
        }

        conclusion.append("根据当前的测量结果，");
        conclusion.append(HealthReportUtil.heightConclusionSimple(record.getChildrenName(), gender, height, record.getMonth() ));

        if(needFinalTip){
            conclusion.append(finalTip);
        }

        return conclusion.toString();
    }

    @Override
    public String getWeightComparingConclusion(EvaluateV2Record record, EvaluateV2Record comparingRecord){
        double weight = 0;
        double pre_weight = 0;
        double height = 0;

        if(StringUtils.isNotBlank(record.getHeight())) {
            height = Double.parseDouble(record.getHeight());
        }
        if(StringUtils.isNotBlank(record.getWeight())) {
            weight = Double.parseDouble(record.getWeight());
        }
        if(StringUtils.isNotBlank(comparingRecord.getWeight())){
            pre_weight = Double.parseDouble(comparingRecord.getWeight());
        }

        String gender = record.getGender() == 0 ? "女" : "男";

        String weightPercent = HealthReportUtil.calcWeightPercent(record.getMonth(), gender, weight );
        String preWeightPercent = HealthReportUtil.calcWeightPercent(record.getMonth(), gender, pre_weight );

        int wi = HealthReportUtil.indexOfPercent(weightPercent) ;
        int pwi = HealthReportUtil.indexOfPercent(preWeightPercent);

//        String conclusion = "实测体重" +String.format("%.2f", weight)+  "kg，按年龄测体重的百分位数为" + weightPercent
//                + "，按身长测体重的百分位数为" + bmiPercent
//                + "。如年龄体重曲线图所示，"
//                + weightConclusionSimple(name, gender, height, weight, month);

        StringBuilder conclusion = new StringBuilder();
        conclusion.append("宝宝本次实测体重");
        conclusion.append(record.getWeight());
        conclusion.append("kg，");
        conclusion.append("较上次测评（");
        conclusion.append(DateUtil.parseToDateDay(comparingRecord.getEvaluatingDate()));

        if(weight > pre_weight) {
            conclusion.append("）体重增加了");
            conclusion.append(String.format("%.2fkg,",  weight - pre_weight));
        }else if(weight < pre_weight){
            conclusion.append("）体重减轻了");
            conclusion.append(String.format("%.2fkg,",  pre_weight - weight));
        }else{
            conclusion.append(") 没有变化。");
        }

        boolean needFinalTip = false;
        final String finalTip = "家长日常生活中应注意：\n" +
                "▪ 食谱每周调整一次，注意干稀、荤素、粗细粮搭配等；\n" +
                "▪ 纠正偏食，从小培养宝宝不挑食的好习惯；少吃零食，避免暴饮暴食。";

        conclusion.append("按年龄测体重的百分位数");
        if(weightPercent.equals(preWeightPercent)){
            conclusion.append("保持在");
            conclusion.append(weightPercent);
            conclusion.append("水平稳步发展。");
            if(wi < 3   /*readablePercent  中*/){
                needFinalTip = true;
            }
        }else {
            if(wi < 3   /*readablePercent  中*/){
                needFinalTip = true;
            }

            conclusion.append("为");
            conclusion.append(weightPercent);
            conclusion.append("，较之前发育水平（");
            conclusion.append(preWeightPercent);
            if (wi > pwi) {
                //增长了
                if(wi - pwi < 2) {
                    conclusion.append("）有所提升。");
                }else{
                    conclusion.append("）显著提升。");
                }
            } else {
                //降低了
                if(pwi - wi < 2) {
                    conclusion.append("）有所下降。");
                }else{
                    conclusion.append("）显著下降。");
                }
                needFinalTip = true;
            }
        }

        conclusion.append("根据当前的测量结果，");
        conclusion.append(HealthReportUtil.weightConclusionSimple(record.getChildrenName(), gender, height, weight, record.getMonth() ));

        if(needFinalTip){
            conclusion.append(finalTip);
        }

        return conclusion.toString();
    }

    @Override
    public int reportDQ(EvaluateV2Record record){
        int dq = 0;

        //创建图表
        int delta = 0;
        for(int i = 0 ; i < record.getDimensionScores().size(); i++){
            EvaluateV2RecordDimensionScore c = record.getDimensionScores().get(i);

            if(c.getDimensionId().equals(WARNING_DIMENSION_ID)) {
                delta = -1;
            }else{
                dq += c.getDq();
            }
        }

        dq /= (record.getDimensionScores().size() + delta);
        dq /= 10;

        return dq;
    }

    @Override
    public String reportRating(EvaluateV2Record record) {
        int dq = reportDQ(record);
        return dqRating(dq);
    }

    @Override
    public String dqRating(int dq){
        // <!--<#if (dqVal >= 130) >-->A++<!--<#elseif (dqVal >= 115)>-->A+<!--<#elseif (dqVal >= 85)>-->A<!--<#elseif (dqVal >= 70)>-->B<!--<#else>-->B-<!--</#if>  -->

        if(dq >= 130){
            return REPORT_RATING_APP.getRating();
        }else if(dq >= 115){
            return REPORT_RATING_AP.getRating();
        } else if(dq >= 85){
            return REPORT_RATING_A.getRating();
        }else if(dq >= 70){
            return REPORT_RATING_B.getRating();
        }else {
            return REPORT_RATING_BM.getRating();
        }
    }


    @Override
    public Map generateReportExtInfo(EvaluateV2Record record){
        Map result = new HashMap();

        List<EvaluateV2AnswerVO> answerSheet = answerRepository.findAnswerSheet(record.getId());
        result.put("answerSheet", answerSheet);

        result.put("id", record.getId());   //?????

        String warningConclusion = getWarningConclusion(record);
        result.put("warningConclusion", warningConclusion);
        //if(StringUtils.isBlank(warningConclusion)) {
            result.put("normalConclusion", getNormalConclusion(record));
        //}


        result.put("bmi", HealthReportUtil.bmiInfo(record.getChildrenName(), record.getGender(), DateUtil.parseToDate(record.getBirthday()), record.getWeight(), record.getHeight()));

        //下次测评时间
        result.put("nextEvaluatingDate", EvaluationReportUtils.nextEvaluateDate(record.getEvaluatingDate(), record.getMonth()));

        //培养建议列表
        List games = EvaluationReportUtils.generateBringUpList(record.getHighLevelInfo());
        result.put("games", games);

        return result;
    }

    //当前月龄总体发育信息
    public String getMonthConclusion(int month){
        List<EvaluateV2MonthConclusion> conclusions = monthConclusionRepository.findAllByMonthOrderBySort(month);

        String ret = "";

        if (conclusions == null || conclusions.size() == 0) {
            return null;
        }

        return ret;
    }

    public static void main(String[] args){
        Date date = DateUtil.parseToDate("2015/8/1");

        double month = DateUtil.betweenMonthsV2(new Date(), date);

        System.out.println("month = " + month);
    }
}
